<template>
  <div class="flexBetween">
    <!-- 左侧组件列表 -->
    <div class="left">
      <div
        class="list-item"
        v-for="item in list1"
        :key="item.code"
        draggable="true"
        @dragstart="(e) => dragstart(e, item)"
        @dragend="dragend"
      >
        {{ item.name }}
      </div>
    </div>
    <!-- 画布区域 -->
    <div class="targetContent" ref="targetContent">
      <div
        class="item"
        v-for="item in list2"
        :key="item.id"
        :ref="item.id"
        :style="{
          top: `${item.top - 16}px`,
          left: `${item.left - 85}px`,
          'z-index': `${item.zIndex}`,
        }"
        @mousedown="(e) => mousedown(e, item)"
      >
        <template v-if="item.code === 'Carousel'">
          <component
            :is="item.code"
            style="width: 200px; user-select: none"
          ></component>
        </template>
        <template v-else>
          <component
            :is="item.code"
            style="width: 400px; user-select: none"
          ></component>
        </template>
      </div>
    </div>
  </div>
</template>

<script>
import _ from "lodash";
export default {
  data() {
    return {
      list1: [
        {
          code: "Carousel",
          name: "轮播图",
          props: {},
        },
        { code: "List", name: "列表内容", id: 2 },
        { code: "Divider", name: "分割线", id: 3 },
      ],
      list2: [],
      dragItem: null,
      moveItem: null,
    };
  },
  methods: {
    dragstart(e, item) {
      this.dragItem = item;
      // 设置元素的放置行为——移动
      this.$refs.targetContent.addEventListener("dragenter", this.dragenter);
      // 在目标元素经过 必须要阻止默认行为 否则不能触发drop
      this.$refs.targetContent.addEventListener("dragover", this.dragover);
      // 离开目标元素时设置元素的放置行为——不能拖放
      this.$refs.targetContent.addEventListener("dragleave", this.dragleave);
      // 拖动元素在目标元素松手时添加元素到画布
      this.$refs.targetContent.addEventListener("drop", this.drop);
    },
    dragend(e) {
      this.$refs.targetContent.removeEventListener("dragenter", this.dragenter);
      this.$refs.targetContent.removeEventListener("dragover", this.dragover);
      this.$refs.targetContent.removeEventListener("dragleave", this.dragleave);
      this.$refs.targetContent.removeEventListener("drop", this.drop);
      console.log(this.list2);
    },
    dragenter(e) {
      e.dataTransfer.dropEffect = "move";
    },
    dragover(e) {
      e.preventDefault();
    },
    dragleave(e) {
      e.dataTransfer.dropEffect = "none";
    },
    drop(e) {
      const { code } = this.dragItem;
      this.list2.push({
        top: e.offsetY,
        left: e.offsetX,
        zIndex: 1,
        code: code,
        id: Date.parse(new Date()),
      });
      this.dragItem = null;
      console.log(1111);
    },
    mousedown(e, item) {
      this.moveItem = item;

      document.addEventListener("mousemove", this.mousemove);
      document.addEventListener("mouseup", this.mouseup);
    },
    mousemove(e) {
      const _this = this;
      let { clientX, clientY } = e;
      const moveIdx = _.findIndex(this.list2, function (o) {
        return o.id === _this.moveItem.id;
      });
      let newList2 = _.cloneDeep(this.list2);
      newList2[moveIdx].top = clientY - 100;
      newList2[moveIdx].left = clientX - 500;
      this.list2 = newList2;

      
    },
    mouseup(e) {
      document.removeEventListener("mousemove", this.mousemove);
      document.removeEventListener("mouseup", this.mouseup);
    },
  },
};
</script>
<style scoped>
.list-item {
  cursor: pointer;
  font-size: 14px;
  padding: 0 12px;
  display: inline-block;
  margin-bottom: 10px;
  margin-right: 10px;
  width: 100px;
  height: 50px;
  line-height: 50px;
  border: 1px solid #bfcbd9;
  /* user-select: none; */
}
.flexBetween {
  width: 100%;
  height: 100%;
}
.left {
  padding: 10px;
  /* position: absolute; */
  width: 270px;
  border: 1px solid rgb(247, 202, 202);
  top: 0;
  bottom: 0;
  left: 0;
}

.targetContent {
  width: calc(100% - 270px);
  border: 1px solid rgb(173, 244, 247);
  height: calc(100% -44px);
}
.item {
  position: absolute;
}
</style>
